home *** CD-ROM | disk | FTP | other *** search
- ;* BLOCK.ASM
- ;************************************************************************
- ;* *
- ;* PC Scheme/Geneva 4.00 Borland TASM code *
- ;* *
- ;* (c) 1985-1988 by Texas Instruments, Inc. See COPYRIGHT.TXT *
- ;* (c) 1992 by L. Bartholdi & M. Vuilleumier, University of Geneva *
- ;* *
- ;*----------------------------------------------------------------------*
- ;* *
- ;* Block Allocation *
- ;* *
- ;*----------------------------------------------------------------------*
- ;* *
- ;* Created by: John Jensen Date: 1985 *
- ;* Revision history: *
- ;* - 18 Jun 92: Renaissance (Borland Compilers, ...) *
- ;* *
- ;* ``In nomine omnipotentii dei'' *
- ;************************************************************************
- IDEAL
- %PAGESIZE 60, 132
- MODEL medium
- LOCALS @@
-
- INCLUDE "scheme.ash"
-
- SMALL_SIZE = 1024 ; space in page not worth searching
-
- CODESEG
-
- ;************************************************************************
- ;* ALLOC_BLOCK *
- ;* *
- ;* calling sequence: alloc_block(reg, type, size) *
- ;************************************************************************
- PROC C alloc_block USES es di si, $$reg:WORD, $$type:WORD, $$size:WORD
- LOCAL @@stringsize:WORD
-
- mov ax, [$$size]
- mov [@@stringsize], ax
- cmp [$$type], STRTYPE ; is it a string?
- jne @@notsmall
- cmp ax, SIZE POINTER ; is it a small string?
- jge @@notsmall
- mov [$$size], SIZE POINTER
- @@notsmall:
- add [$$size], OFFSET (TYPE ANYDEF).data
-
- call search_block ; search page type chain for block
- jnc @@failed
- jmp @@done
-
- @@failed: ; Didn't find a block, search a new page
- mov ax, [$$size]
- cmp [emspages], 0
- jne @@findapage
- cmp ax, [defpagesize] ; without EMS, we can't find a larger one
- jae @@findabigone
- @@findapage:
- call alloc_page C, [$$type], ax
- cmp ax, END_LIST ; did we succeed?
- jne @@newpagefound
- ; no more pages, try a garbage collection,
- ; then search the pages again for a free block
- mov si, [$$reg]
- mov [(REG si).page], NIL_PAGE*2 ; clear reg before GC
- call garbage C
- call search_block
- jc @@done
- ; Still couldn't find a block large enough, try to allocate a new page once
- ; again (since we just did a garbage collection).
- call alloc_page C, [$$type], [$$size]
- cmp ax, END_LIST ; did we succeed?
- jnz @@newpagefound
- ; We're getting desperate now. Try a collection with compaction, then try to
- ; allocate a new page for the object
- mov si, [$$reg]
- mov [(REG si).page], NIL_PAGE*2 ; clear for possible GC
- call gcsquish C
- call alloc_page C, [$$type], [$$size]
- cmp ax, END_LIST ; did we succeed?
- jne @@newpagefound
- @@findabigone:
- mov si, [$$reg] ; try allocating a big block, then
- mov [(REG si).page], NIL_PAGE*2 ; clear ret reg in case of GC
- call alloc_big_block C, si, [$$type], [$$size]
- jmp @@done
-
- @@newpagefound: ; ax is the page # found
- push es ; save es over C call
- call find_block C, [$$reg], [$$type], [$$size], ax
- pop es
- or ax, ax ; ax nul = success
- jnz @@error
- @@done: ; We have found a block, set up the header and return
- cmp [$$type], STRTYPE
- jne @@ret
- cmp [@@stringsize], SIZE POINTER
- jge @@ret
- push es ; for small strings, put the negative value for object length
- mov si, [$$reg]
- mov bx, [(REG si).page]
- mov si, [(REG si).disp]
- ldpage es, bx
- mov cx, [@@stringsize]
- sub cx, SIZE POINTER
- mov [(STRDEF es:si).len], cx
- pop es
- @@ret:
- ret
-
- @@error:
- call out_of_memory C
- jmp @@ret ; control will not return here
-
- ;************************************************************************
- ;* SRCH_BLOCK - Search through all the pages of a given type looking *
- ;* for a block large enough to fill the size request. *
- ;* *
- ;* Upon Exit: Carry Flag set, $$reg will point to the block. *
- ;* Carry Flag clear, $$reg will contain a page # of -1 *
- ;************************************************************************
- PROC search_block NEAR
- mov si, [$$type]
- lea bx, [pagelist+si]
- push bx ; save the last page
- mov ax, [pagelist+si] ; ax = page number for this type
- cmp ax, END_LIST ; any pages to search?
- clc ; carry clear = failure
- je @@searchend
- @@searchloop:
- mov si, ax ; save page number for later
- call find_block C, [$$reg], [$$type], [$$size], ax
- or ax, ax ; ax nul = success
- stc ; assume success
- jz @@searchend
- ; Block not found within current page.
- shl si, 1 ; make page # into index
- cmp [$$size], SMALL_SIZE
- jg @@searchbigenough
- ; less than small_size space is left within the page; this isn't worth searching
- ; again, so update the last position in the chain (last page) to point to the
- ; next page in the chain.
- mov ax, [pagelink+si]
- pop di ; peep at the last page
- push di
- mov [di], ax
- @@searchbigenough:
- ; update last_page to contain the address of the next position in the chain,
- ; and get the next page from pagelink[page].
- lea bx, [pagelink+si]
- pop ax ; trash & reload the last page
- push bx
- mov ax, [bx]
- cmp ax, END_LIST ; reached end of chain?
- jne @@searchloop
- clc ; carry clear = failure
- @@searchend:
- pop ax ; trash off the last page
- ret
- ENDP search_block
- ENDP alloc_block
-
- ;************************************************************************
- ;* FIND_BLOCK *
- ;* *
- ;* calling sequence: find_block(reg, type, size, page) *
- ;* *
- ;* Upon Exit: ax = 0: reg contains page:displ of new block *
- ;* ax = -1: reg contains page of -1 *
- ;************************************************************************
- PROC C find_block USES si di, @@reg:WORD, @@type:WORD, @@size:WORD, @@page:WORD
-
- mov si, [@@reg]
- mov [(REG si).page], -1 ; default to block not found
-
- mov si, [@@page] ; get page number
- shl si, 1
- ldpage es, si
-
- mov bx, [nextcell+si] ; lets see if there's space in the free pool of this block
- cmp bx, END_LIST
- je @@pageempty
- mov ax, [(FREEDEF es:bx).len]
- mov dx, [@@size]
- cmp ax, dx
- jl @@pageempty
-
- ; allocate a block from the free pool.
- ; ax = free pool size, bx = displacement, dx = object size
- mov cx, [@@type]
- mov [(ANYDEF es:bx).tag], cl
- mov [(ANYDEF es:bx).len], dx
- mov di, bx
- add di, dx ; di is end of new block
- mov cx, [psize+si] ; get page size
- sub cx, OFFSET (TYPE ANYDEF).data
- cmp cx, di ; next disp still in page?
- jb @@pagefull
- mov [(FREEDEF es:di).tag], FREETYPE
- sub ax, dx ; ax = pool size - object size
- mov [(FREEDEF es:di).len], ax
- mov [nextcell+si], di
- jmp @@done
- @@pagefull:
- mov [nextcell+si], END_LIST
- jmp @@done
-
- ; A block was not found in the free pool. Search the entire block for a fragment
- ; to satisfy the request.
- @@pageempty:
- xor bx, bx ; bx = displacement
- mov cx, [psize+si]
- sub cx, [@@size] ; cx = displacement threshold
- cmp cx, bx
- mov ax, -1 ; zero flag not set = failure
- jl @@ret ; return with no block found
-
- @@loop: ; the following loop requires bx=displacement, cx=threshold, dx=free size
- mov dx, [(ANYDEF es:bx).len]
- cmp [(ANYDEF es:bx).tag], FREETYPE
- je @@found
- @@infactnotfound:
- mov ax, OFFSET (TYPE STRDEF).buffer + SIZE POINTER ; ax = ovhd for small string
- or dx, dx
- js @@smallstring
- mov ax, dx ; else ax = size of object
- @@smallstring:
- add bx, ax ; displacement += size
- cmp cx, bx ; disp <= threshold ?
- jge @@loop
- mov ax, -1 ; zero flag not set = failure
- jmp @@ret ; return with no block found
-
- ;we have found a free space in the block; if not big enough then jump back
- ;into loop above, otherwise allocate the new storage
- @@found:
- mov ax, [@@size]
- cmp ax, dx ; compare size to free size
- jl @@infactnotfound
- jne @@partialmatch
- mov ax, [@@type] ; we found an exact match
- mov [(ANYDEF es:bx).tag], al
- jmp @@done
- @@partialmatch:
- mov di, dx
- sub di, OFFSET (TYPE ANYDEF).data
- cmp di, ax ; can an object fit into the free space?
- jle @@infactnotfound
- ; we can fit into a larger block, split block to allocate storage
- mov cx, [@@type]
- mov [(ANYDEF es:bx).tag], cl
- mov [(ANYDEF es:bx).len], ax
- mov di, bx ; ax=new object size, bx=disp, dx=free size
- add di, ax ; update to end of block
- sub dx, ax ; free size - new size
- mov [(FREEDEF es:di).tag], FREETYPE
- mov [(FREEDEF es:di).len], dx
- ; block found; return page,disp in return register.
- ; si = page index, bx = displacement
- @@done:
- mov di, [@@reg]
- mov [(REG di).page], si
- mov [(REG di).disp], bx
- xor ax, ax ; ax nul = success
- @@ret:
- ret
- ENDP find_block
-
- END
-